﻿#region Copyright

// All Material Copyright © 2010 Dynamic Concepts Development Corp., All Rights Reserved.
//      Portions Copyright © 1984-2009 Dynamic Concepts Development Corp., All Rights Reserved.
// For further information please contact: SoftwareSupport@dynconcepts.com
// Dynamic Concepts Development Corp.  311 W 57th St. Suite #422, New York, NY 10019

#endregion

#region Using References

using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Threading;
using DynConDevCorp.OpenArch.SupportLibrary.ApplicationInfrastructure;

#endregion

namespace DynConDevCorp.OpenArch.SupportLibrary.ParallelExecution
{
    public class ParallelHostThread : DispatcherObject
    {
        #region Constructors

        private ParallelHostThread(DispatcherObject mainObject)
        {
            r_MainObject = mainObject;
        }

        #endregion

        #region Public Methods

        public static void CreateNew(DispatcherObject mainObject)
        {
            CreateNew(mainObject, null);
        }

        public static void CreateNew(DispatcherObject mainObject, EventHandler applicationThreadStarted)
        {
            ParallelHostThread instance = new ParallelHostThread(mainObject);
            s_Instances.Add(instance);
            if (applicationThreadStarted != null)
                applicationThreadStarted(instance, new EventArgs());
            instance.Execute();
        }

        public void Execute()
        {
            if (m_EnableLogging) QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "ParallelHostThread.Execute() - Entered");
            Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
            Dispatcher.ShutdownFinished += Dispatcher_ShutdownFinished;
            while (!m_ShutDownRequested)
            {
                try
                {
                    Dispatcher.Run();
                }
                catch (Exception ex)
                {
                    if (m_EnableLogging) QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "ParallelHostThread.Execute() - Exception: {0}", ex.Message);
                }
            }
            if (m_EnableLogging) QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "ParallelHostThread.Execute() - Exiting");
            IDisposable asDisposable = r_MainObject as IDisposable;
            if (asDisposable != null)
            {
                asDisposable.Dispose();
            }
            m_ShutdownSemaphore.Release();
        }

        public static void ProcessThreadMessages()
        {
        }

        public void ShutDown()
        {
            if (!m_ShutDownRequested)
            {
                m_ShutDownRequested = true;
                if (m_EnableLogging) QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "ParallelHostThread.Shutdown()");
                m_ShutdownSemaphore = new Semaphore(0, 1);
                Dispatcher.BeginInvokeShutdown(DispatcherPriority.ApplicationIdle);
            }
        }

        public static void ShutDownAll()
        {
            if (c_EnableLogging) QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "ParallelHostThread.ShutDownAll() - Started");
            foreach (ParallelHostThread thread in s_Instances)
            {
                thread.ShutDown();
                thread.WaitForShutDown();
            }
            s_Instances.Clear();
            if (c_EnableLogging) QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "ParallelHostThread.ShutDownAll() - Complete");
        }

        public void WaitForShutDown()
        {
            if (m_EnableLogging) QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "ParallelHostThread.WaitForShutDown() - Entered");
            m_ShutdownSemaphore.WaitOne();
            if (m_EnableLogging) QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "ParallelHostThread.WaitForShutDown() - Exiting");
        }

        #endregion

        #region Private Methods

        private void Dispatcher_ShutdownFinished(object sender, EventArgs e)
        {
            if (m_EnableLogging) QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "ParallelHostThread.Dispatcher_ShutdownFinished()");
        }

        private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
        {
            if (m_EnableLogging) QueuedLogger.GlobalInstance.Log(QueuedLogger.MessageSeverity.Debug, "ParallelHostThread.Dispatcher_ShutdownStarted()");
        }

        #endregion

        #region Static Fields and Constants

        private const bool c_EnableLogging = false;
        private static readonly List<ParallelHostThread> s_Instances = new List<ParallelHostThread>();

        #endregion

        #region Instance Fields (ReadOnly)

        private readonly DispatcherObject r_MainObject;

        #endregion

        #region Instance Fields (Mutable)

        private bool m_EnableLogging = c_EnableLogging;
        private bool m_ShutDownRequested;
        private Semaphore m_ShutdownSemaphore = new Semaphore(0, 1);

        #endregion
    }
}